from  flask_classy import FlaskView, route
from ..schema.param import shop_cart_item_param, currency_param
from ..schema.error import PRODUCT_NOT_EXIST, STOCK_NOT_EXIST, PARAMS_ERROR, PARAMS_DOES_NOT_EXIST, MEMBER_NOT_EXIST
from  flask import request
from ..models.product import Product
from ..models.offer import Offer
from ..models.shop_cart import CartItem, ShopCart, CartItemAdditive
from ..schema.object import success_schema, ShopCharItemSchema, currency_schema
from marshmallow.exceptions import ValidationError
from ..models.currency import Currency
from ..models.service import Service
from ..models.member import Member
from ..database import database
import datetime


class ShopCartItemsView(FlaskView):
    @route('/source/<source>')
    def fetch_items(self, source):

        params, _ = currency_param.load(request.values)

        currency = params.get('currency') or Currency.get_main_currency()

        shop_cart_items_schema = ShopCharItemSchema(many=True, context={'currency': currency})

        items = CartItem.get_by_source(source)

        return success_schema.jsonify(
            {
                'currency': currency_schema.dump(currency).data,
                'cart_items': shop_cart_items_schema.dump(
                    items).data
            }
        )

    @route('/', methods=['POST'])
    def create_shop_cart_item(self):
        print(request.json)
        if request.data:
            data = {}
            try:
                data, _ = shop_cart_item_param.loads(request.data.decode(request.charset))
            except   ValidationError  as  ve:
                return PARAMS_ERROR.jsonify(ve)

            offer = Offer.get_or_none(Offer.id == data.get('offer'))

            if not offer:
                return STOCK_NOT_EXIST.jsonify()

            product = offer.product

            with  offer.atomic():
                shop_cart = None
                if 'member' in data and data['member']:
                    member = Member.get_member(data['member'])

                    if member:
                        shop_cart, _ = ShopCart.get_or_create(member=member, defaults={
                            'member': member,
                            'updated_at': datetime.datetime.now()
                        })
                    else:
                        return MEMBER_NOT_EXIST.jsonify()
                count = data.get('count', 1)

                cart_item = CartItem.get_item_from(data.get('source'), product, offer)

                if cart_item:
                    cart_item.count += count
                    cart_item.shop_cart = shop_cart

                else:
                    cart_item = CartItem.create(
                        shop_cart=shop_cart,
                        source=data.get('source'),
                        product=product,
                        stock=offer,
                        count=count
                    )
                CartItemAdditive.delete_all_for(cart_item)
                if 'additives' in data:
                    for n in data['additives']:
                        type = n['type']
                        title = ''
                        if type == 'service':
                            service = Service.get_or_none(Service.id == n['ref_id'])
                            if not service:
                                pass
                            else:
                                title = service.screen_name
                                CartItemAdditive.create(
                                    type=n['type'],
                                    ref_id=n['ref_id'],
                                    cart_item=cart_item,
                                    title=title,
                                    required=n.get('required') if 'required' in n else 'N'
                                )
                                # cart_item.additives.add(additive)
                if cart_item.is_dirty:
                    cart_item.save()
            return success_schema.jsonify()

        else:
            return PARAMS_DOES_NOT_EXIST.jsonify()
